package schema

import (
	"lianzi_gos/internal/config"
	"strings"
	"time"

	"lianzi_gos/pkg/util"
)

// 分类表
type Category struct {
	ID          string      `json:"id" gorm:"size:20;primarykey;"`      // Unique ID
	Name        string      `json:"name" gorm:"size:128;index"`         // 分类名称
	Img         string      `json:"img" gorm:"size:200;index"`          // 分类图片
	Description string      `json:"description" gorm:"size:1024"`       // 图片
	Sequence    int         `json:"sequence" gorm:"index;"`             // Sequence for sorting
	Status      string      `json:"status" gorm:"size:20;index"`        // Status of dictionary (disabled, enabled)
	ParentID    string      `json:"parent_id" gorm:"size:20;index;"`    // Parent ID (From Category.ID)
	ParentPath  string      `json:"parent_path" gorm:"size:255;index;"` // Parent path (split by .)
	Children    *Categories `json:"children" gorm:"-"`                  // Child nodes
	CreatedAt   time.Time   `json:"created_at" gorm:"index;"`           // Create time
	UpdatedAt   time.Time   `json:"updated_at" gorm:"index;"`           // Update time
}

func (a *Category) TableName() string {
	return config.C.FormatTableName("category")
}

// Defining the query parameters for the `Category` struct.
type CategoryQueryParam struct {
	util.PaginationParam
	InIDs            []string `form:"-"`
	LikeName         string   `form:"name"` // 分类名称
	Status           string   `form:"-"`    // Status of dictionary (disabled, enabled)
	ParentID         string   `form:"-"`    // Parent ID (From Category.ID)
	ParentPathPrefix string   `form:"-"`    // Parent path (split by .)
}

// Defining the query options for the `Category` struct.
type CategoryQueryOptions struct {
	util.QueryOptions
}

// Defining the query result for the `Category` struct.
type CategoryQueryResult struct {
	Data       Categories
	PageResult *util.PaginationResult
}

// Defining the slice of `Category` struct.
type Categories []*Category

func (a Categories) Len() int {
	return len(a)
}

func (a Categories) Less(i, j int) bool {
	if a[i].Sequence == a[j].Sequence {
		return a[i].CreatedAt.Unix() > a[j].CreatedAt.Unix()
	}
	return a[i].Sequence > a[j].Sequence
}

func (a Categories) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}
func (a Categories) ToMap() map[string]*Category {
	m := make(map[string]*Category)
	for _, item := range a {
		m[item.ID] = item
	}
	return m
}

func (a Categories) SplitParentIDs() []string {
	parentIDs := make([]string, 0, len(a))
	idMapper := make(map[string]struct{})
	for _, item := range a {
		if _, ok := idMapper[item.ID]; ok {
			continue
		}
		idMapper[item.ID] = struct{}{}
		if pp := item.ParentPath; pp != "" {
			for _, pid := range strings.Split(pp, util.TreePathDelimiter) {
				if pid == "" {
					continue
				}
				if _, ok := idMapper[pid]; ok {
					continue
				}
				parentIDs = append(parentIDs, pid)
				idMapper[pid] = struct{}{}
			}
		}
	}
	return parentIDs
}

func (a Categories) ToTree() Categories {
	var list Categories
	m := a.ToMap()
	for _, item := range a {
		if item.ParentPath == "" {
			list = append(list, item)
			continue
		}
		if parent, ok := m[item.ParentID]; ok {
			if parent.Children == nil {
				children := Categories{item}
				parent.Children = &children
				continue
			}
			*parent.Children = append(*parent.Children, item)
		}
	}
	return list
}

// Defining the data structure for creating a `Category` struct.
type CategoryForm struct {
	Name        string `json:"name" binding:"required,max=128"`                  // 分类名称
	Description string `json:"description"`                                      // 图片
	Sequence    int    `json:"sequence"`                                         // Sequence for sorting
	Status      string `json:"status" binding:"required,oneof=disabled enabled"` // Status of dictionary (disabled, enabled)
	ParentID    string `json:"parent_id"`                                        // Parent ID (From Category.ID)
}

// A validation function for the `CategoryForm` struct.
func (a *CategoryForm) Validate() error {
	return nil
}

// Convert `CategoryForm` to `Category` object.
func (a *CategoryForm) FillTo(category *Category) error {
	category.Name = a.Name
	category.Description = a.Description
	category.Sequence = a.Sequence
	category.Status = a.Status
	category.ParentID = a.ParentID
	return nil
}
